#ifndef KGSL_UTILS_H
#define KGSL_UTILS_H

#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>

#define KGSL_MEMFLAGS_USE_CPU_MAP 0x10000000ULL

#define KGSL_MEMFLAGS_GPUREADONLY 0x01000000U

#define KGSL_OBJLIST_MEMOBJ  0x00000008U
#define KGSL_OBJLIST_PROFILE 0x00000010U
#define KGSL_DRAWOBJ_PROFILING      0x00000010
#define KGSL_MEMFLAGS_IOCOHERENT  (1ULL << 31)

enum kgsl_user_mem_type {
	KGSL_USER_MEM_TYPE_PMEM		= 0x00000000,
	KGSL_USER_MEM_TYPE_ASHMEM	= 0x00000001,
	KGSL_USER_MEM_TYPE_ADDR		= 0x00000002,
	KGSL_USER_MEM_TYPE_ION		= 0x00000003,
	/*
	 * ION type is retained for backwards compatibility but Ion buffers are
	 * dma-bufs so try to use that naming if we can
	 */
	KGSL_USER_MEM_TYPE_DMABUF       = 0x00000003,
	KGSL_USER_MEM_TYPE_MAX		= 0x00000007,
};

struct kgsl_timeline_fence_get {
	__u64 seqno;
	__u32 timeline;
	int handle;
};

#define IOCTL_KGSL_TIMELINE_FENCE_GET \
	_IOWR(KGSL_IOC_TYPE, 0x5C, struct kgsl_timeline_fence_get)


struct kgsl_timeline_create {
	__u64 seqno;
	__u32 id;
/* private: padding for 64 bit compatibility */
	__u32 padding;
};

#define IOCTL_KGSL_TIMELINE_CREATE \
	_IOWR(KGSL_IOC_TYPE, 0x58, struct kgsl_timeline_create)

#define IOCTL_KGSL_TIMELINE_DESTROY _IOW(KGSL_IOC_TYPE, 0x5D, __u32)

struct kgsl_device_getproperty {
	unsigned int type;
	void *value;
	size_t sizebytes;
};

#define IOCTL_KGSL_DEVICE_GETPROPERTY \
	_IOWR(KGSL_IOC_TYPE, 0x2, struct kgsl_device_getproperty)


struct kgsl_gpumem_alloc_id {
	unsigned int id;
	unsigned int flags;
	uint64_t size;
	uint64_t mmapsize;
	unsigned long gpuaddr;
};

#define IOCTL_KGSL_GPUMEM_ALLOC_ID \
	_IOWR(KGSL_IOC_TYPE, 0x34, struct kgsl_gpumem_alloc_id)

struct kgsl_command_object {
    uint64_t offset;
    uint64_t gpuaddr;
    uint64_t size;
    unsigned int flags;
    unsigned int id;
};

struct kgsl_gpu_command {
	uint64_t flags;
	uint64_t __user cmdlist;
	unsigned int cmdsize;
	unsigned int numcmds;
	uint64_t __user objlist;
	unsigned int objsize;
	unsigned int numobjs;
	uint64_t __user synclist;
	unsigned int syncsize;
	unsigned int numsyncs;
	unsigned int context_id;
	unsigned int timestamp;
};

struct kgsl_map_user_mem {
    int fd;
    unsigned long gpuaddr;   /*output param */
    size_t len;
    size_t offset;
    unsigned long hostptr;   /*input param */
    enum kgsl_user_mem_type memtype;
    unsigned int flags;
};

struct kgsl_drawctxt_create {
    unsigned int flags;
    unsigned int drawctxt_id; /*output param */
};

/* destroy a draw context */
struct kgsl_drawctxt_destroy {
    unsigned int drawctxt_id;
};


#define KGSL_IOC_TYPE 0x09

#define IOCTL_KGSL_DRAWCTXT_CREATE \
        _IOWR(KGSL_IOC_TYPE, 0x13, struct kgsl_drawctxt_create)

#define IOCTL_KGSL_DRAWCTXT_DESTROY \
        _IOW(KGSL_IOC_TYPE, 0x14, struct kgsl_drawctxt_destroy)

#define IOCTL_KGSL_MAP_USER_MEM \
        _IOWR(KGSL_IOC_TYPE, 0x15, struct kgsl_map_user_mem)

#define IOCTL_KGSL_GPU_COMMAND \
        _IOWR(KGSL_IOC_TYPE, 0x4A, struct kgsl_gpu_command)

#define KGSL_CMDLIST_IB             0x00000001U
#define KGSL_MEMFLAGS_USE_CPU_MAP   0x10000000ULL

struct kgsl_gpuobj_import {
	uint64_t __user priv;
	uint64_t priv_len;
	uint64_t flags;
	unsigned int type;
	unsigned int id;
};

struct kgsl_gpuobj_import_dma_buf {
	int fd;
};

struct kgsl_gpuobj_import_useraddr {
	uint64_t virtaddr;
};

struct kgsl_gpuobj_free {
	uint64_t flags;
	uint64_t __user priv;
	unsigned int id;
	unsigned int type;
	unsigned int len;
};

#define KGSL_GPUOBJ_FREE_ON_EVENT 1

#define KGSL_GPU_EVENT_TIMESTAMP 1
#define KGSL_GPU_EVENT_FENCE     2

struct kgsl_gpu_event_timestamp {
	unsigned int context_id;
	unsigned int timestamp;
};

struct kgsl_gpu_event_fence {
	int fd;
};

struct kgsl_gpumem_free_id {
	unsigned int id;
/* private: reserved for future use*/
	unsigned int __pad;
};

#define IOCTL_KGSL_GPUMEM_FREE_ID _IOWR(KGSL_IOC_TYPE, 0x35, struct kgsl_gpumem_free_id)

#define IOCTL_KGSL_GPUOBJ_FREE \
	_IOW(KGSL_IOC_TYPE, 0x46, struct kgsl_gpuobj_free)

struct dma_buf_sync {
	__u64 flags;
};

#define DMA_BUF_SYNC_READ      (1 << 0)
#define DMA_BUF_SYNC_WRITE     (2 << 0)
#define DMA_BUF_SYNC_RW        (DMA_BUF_SYNC_READ | DMA_BUF_SYNC_WRITE)
#define DMA_BUF_SYNC_START     (0 << 2)
#define DMA_BUF_SYNC_END       (1 << 2)
#define DMA_BUF_SYNC_USER_MAPPED       (1 << 3)

#define DMA_BUF_SYNC_VALID_FLAGS_MASK \
	(DMA_BUF_SYNC_RW | DMA_BUF_SYNC_END)

#define DMA_BUF_BASE		'b'
#define DMA_BUF_IOCTL_SYNC	_IOW(DMA_BUF_BASE, 0, struct dma_buf_sync)

#define KGSL_MEMFLAGS_FORCE_32BIT 0x100000000ULL


struct kgsl_syncsource_create {
	unsigned int id;
/* private: reserved for future use */
	unsigned int __pad[3];
};

#define IOCTL_KGSL_SYNCSOURCE_CREATE \
	_IOWR(KGSL_IOC_TYPE, 0x40, struct kgsl_syncsource_create)

struct kgsl_syncsource_create_fence {
	unsigned int id;
	int fence_fd;
/* private: reserved for future use */
	unsigned int __pad[4];
};

/**
 * struct kgsl_syncsource_signal_fence - Argument to
 *     IOCTL_KGSL_SYNCSOURCE_SIGNAL_FENCE
 * @id: syncsource id
 * @fence_fd: sync_fence fd to signal
 *
 * Signal a fence that was created by a IOCTL_KGSL_SYNCSOURCE_CREATE_FENCE
 * call using the same syncsource id. This allows a fence to be shared
 * to other processes but only signaled by the process owning the fd
 * used to create the fence.
 */
#define IOCTL_KGSL_SYNCSOURCE_CREATE_FENCE \
	_IOWR(KGSL_IOC_TYPE, 0x42, struct kgsl_syncsource_create_fence)

int kgsl_ctx_create(int fd, uint32_t *ctx_id);
int kgsl_gpu_command_payload(int fd, uint32_t ctx_id, uint64_t gpuaddr, uint32_t cmdsize, uint32_t n, uint32_t target_idx, uint64_t target_cmd, uint32_t target_size);
int kgsl_map(int fd, unsigned long addr, size_t len, uint64_t *gpuaddr, int readonly);

#endif
